package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceDataMapper;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.mapper.UserMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceDataGraphVo;
import com.zzyl.vo.DeviceDataVo;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description ProductServiceImpl
 * @Author Hua Caoxing
 * @Data 2025-09-10
 */

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private Client client;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DeviceDataMapper deviceDataMapper;


    /**
     * 从物联网平台同步产品列表
     */
    @Override
    public void syncProductList() {

        QueryProductListRequest request = new QueryProductListRequest();
        request.setPageSize(200);
        request.setCurrentPage(1);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryProductListResponse response = null;

        try {
            // 从物联网平台同步餐品列表

             response = client.queryProductList(request);
        } catch (Exception e) {
           throw new RuntimeException(response.getBody().getErrorMessage());
        }

        if (!response.getBody().getSuccess()){
           throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }
        List<ProductVo> productVoList = response.getBody().getData().getList().getProductInfo().stream()
                .map(p -> BeanUtil.toBean(p, ProductVo.class))
                .collect(Collectors.toList());
        // 同步到redis
        redisTemplate.opsForValue().set(CacheConstants.PRODUCT_LIST, JSONUtil.toJsonStr(productVoList));

    }

    /**
     * 查询所有产品
     * @return
     */
    @Override
    public List<ProductVo> allProduct() {
        String productList = redisTemplate.opsForValue().get(CacheConstants.PRODUCT_LIST);
        if (productList == null){
            return Collections.emptyList();
        }

        return JSONUtil.toList(productList, ProductVo.class);
    }

    /**
     * 注册设备
     * @param deviceDto
     */
    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //检查设备名称是否重复
        Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if (count > 0){
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        RegisterDeviceResponse registerDeviceResponse = null;
        //Iot注册设备
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
             registerDeviceResponse = client.registerDevice(request);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        //判断是否注册成功
        if (!registerDeviceResponse.getBody().getSuccess()){
            throw new RuntimeException(registerDeviceResponse.getBody().getErrorMessage());
        }
        //注册成功，查询产品名称
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductResponse queryProductResponse = null;
        try{
            queryProductResponse  = client.queryProduct(queryProductRequest);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        //判断查询是否成功
        if (!queryProductResponse.getBody().getSuccess()){
            throw new RuntimeException(queryProductResponse.getBody().getErrorMessage());
        }
        Device device = BeanUtil.toBean(deviceDto,Device.class);
        device.setProductName(queryProductResponse.getBody().getData().getProductName());
        device.setIotId(registerDeviceResponse.getBody().getData().getIotId());

        //根据位置类型判断物理位置类型
        if (device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        deviceMapper.insertSelective(device);

    }

    /**
     * 分页查询设备
     * @param devicePageQueryDto
     * @return
     */
    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(),devicePageQueryDto.getPageSize());

        Page<DeviceVo> deviceVoPage = (Page<DeviceVo>)deviceMapper.pageQueryDevice(devicePageQueryDto);


        return PageResponse.of(deviceVoPage, DeviceVo.class);
    }


    /**
     * 查询设备详情
     * @param deviceDto
     * @return
     */
    @Override
    public DeviceVo QueryDeviceDetail(DeviceDto deviceDto) {
        //查询数据库是否存在对应数据
        DeviceVo deviceVo = deviceMapper.selectByProductKey(deviceDto.getIotId());
        if (deviceVo == null){
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }
        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setIotId(deviceDto.getIotId());
        QueryDeviceDetailResponse response = null;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //判断是否查询成功
        if (!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        BeanUtil.copyProperties(response.getBody().getData(),deviceVo);

        //存在直接返回
        return deviceVo;

    }

    /**
     * 查看指定产品的已发布物模型中的功能定义详情
     *
     * @param
     * @return
     */
    @Override
    public ResponseResult <QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData> QueryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response = null;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        //判断是否查询成功
        if (!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        return ResponseResult.success(response.getBody().getData());
    }

    /**
     * 修改设备
     * @param deviceDto
     */
    @Override
    public void UpdateDevice(DeviceDto deviceDto) {
        //判断设备是否存在
        Device device = deviceMapper.selectByPrimaryKey(deviceDto.getId());
        if (ObjectUtil.isEmpty(device)) {
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }

        Device newDevice = BeanUtil.toBean(deviceDto, Device.class);
        //根据位置类型判断物理位置类型
        if (device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }
        //更新数据库
        deviceMapper.updateByPrimaryKeySelective(newDevice);

        //调用物联网接口，更新云服务设备信息，这里只会更新阿里云那边的昵称，产品分类和设备名称一旦创建不允许再修改
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
        BatchUpdateDeviceNicknameResponse response = null;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

    }

    /**
     * 删除数据
     * @param deviceDto
     */
    @Override
    public void DeleteDevice(DeviceDto deviceDto) {
        //判断设备是否存在
        DeviceVo deviceVo = deviceMapper.selectByProductKey(deviceDto.getIotId());
        if (ObjectUtil.isEmpty(deviceVo)) {
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }
        deviceMapper.deleteByPrimaryKey(deviceVo.getId());

        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setIotId(deviceVo.getIotId());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        DeleteDeviceResponse response = null;
        try {
             response = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
    }

    /**
     * 按天统计查询指标数据
     * @param iotId 设备id
     * @param endTime 结束时间
     * @param startTime 开始时间
     * @param functionId 物理模型id
     * @return
     */
    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByDay(String iotId, Long endTime, Long startTime, String functionId) {
        List<DeviceDataGraphVo> deviceDataGraphVosNew = DeviceDataGraphVo.dayInstance(LocalDateTimeUtil.of(startTime));

        List<DeviceDataGraphVo>  deviceDataGraphVos = deviceDataMapper.countbyfunctionId(iotId, LocalDateTimeUtil.of(startTime),LocalDateTimeUtil.of(endTime),functionId);

        Map<String, Double> map = deviceDataGraphVos.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));

        deviceDataGraphVosNew.forEach(d -> {
            //从map获取值，如果为空，则给默认为0
            Double val = map.get(d.getDateTime()) == null ? 0.0 : map.get(d.getDateTime());
            d.setDataValue(val);
        });

        return deviceDataGraphVosNew;
    }

    /**
     * 按周查询设备数据
     * @param iotId
     * @param functionId
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByWeek(String iotId, String functionId, Long startTime, Long endTime) {

        List<DeviceDataGraphVo> deviceDataGraphVos = DeviceDataGraphVo.weekInstance(LocalDateTimeUtil.of(startTime));

        List<DeviceDataGraphVo> list = deviceDataMapper.queryDeviceDataListByWeek(iotId,functionId,LocalDateTimeUtil.of(startTime),LocalDateTimeUtil.of(endTime));

        Map<String, Double> map = list.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));

        deviceDataGraphVos.forEach(deviceDataGraphVo -> {
            //从map获取值，如果为空，则给默认为0
            Double val = map.get(deviceDataGraphVo.getDateTime()) == null ? 0.0 : map.get(deviceDataGraphVo.getDateTime());
            deviceDataGraphVo.setDataValue(val);
                }
        );

        return deviceDataGraphVos;
    }


    /**
     * 查询指定设备的物模型运行状态
     * @param queryDevicePropertyStatusRequest
     * @return
     */
    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData QueryDevicePropertyStatus(QueryDevicePropertyStatusRequest queryDevicePropertyStatusRequest) {

        queryDevicePropertyStatusRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryDevicePropertyStatusResponse response =null;
        try {
           response = client.queryDevicePropertyStatus(queryDevicePropertyStatusRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
       if (!response.getBody().getSuccess()){
           throw new RuntimeException(response.getBody().getErrorMessage());
       }

        return response.getBody().getData();
    }
}
